package com.wkk.websocket.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wkk.authentication.entity.UmsUser;
import com.wkk.exception.NoBugException;
import com.wkk.utils.NoBugTools;
import com.wkk.websocket.config.WebSocketHandle;
import com.wkk.websocket.constant.WebSocketConstant;
import com.wkk.websocket.dto.MessageChatDto;
import com.wkk.websocket.dto.MessageSendDto;
import com.wkk.websocket.entity.Message;
import com.wkk.websocket.mapper.MessageMapper;
import com.wkk.websocket.service.MessageService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

/**
 * @author : WangKeKe
 * @date : 2020/8/18 14:10
 * Description : 消息服务接口实现类
 */

@Slf4j
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {

    @Autowired
    private WebSocketHandle webSocketHandle;

    @Override
    @Transactional(rollbackFor = NoBugException.class)
    public boolean sendMsg(MessageSendDto messageSendDto) {

        // 从认证机制中获得用户信息
        Subject subject = SecurityUtils.getSubject();
        UmsUser umsUser = (UmsUser) subject.getPrincipal();
        // 分割接收者 - 由于做了后端校验，保证该数据不为空
        String receiveIds = messageSendDto.getReceiveIds();
        List<String> ids = Arrays.asList(receiveIds.split(","));
        // 将消息的公共内容赋值 - 持久化消息
        Message message = new Message()
                // 文本内容
                .setContent(messageSendDto.getContent())
                // 发送者ID
                .setSendId(umsUser.getId())
                // 区分私发与群发
                .setMsgType(ids.size() == 1 ? WebSocketConstant.MSG_TYPE_SINGLE : WebSocketConstant.MSG_TYPE_GROUP);
        // 前端显示的消息 - 传输
        MessageChatDto messageChatDto = new MessageChatDto()
                .setHeadUrl(umsUser.getHeadUrl())
                .setNickname(umsUser.getNickname())
                .setSendUserId(umsUser.getId())
                .setMsgContent(messageSendDto.getContent())
                .setMsgType(ids.size() == 1 ? WebSocketConstant.MSG_TYPE_SINGLE : WebSocketConstant.MSG_TYPE_GROUP);
        // 日志计数
        int successCount = 0;
        int failCount = 0;
        for (String receiveId : ids) {
            message.setReceiveId(receiveId);
            // 这里先要持久化，再发送消息 - 因为要获取消息的ID
            // 需要将ID重置 否则就需要创建多个Message对象
            message.setId(null);
            baseMapper.insert(message);
            log.info("插入消息>>>>>>>>>ID: " + message.getId());
            // 如果出现发送异常，则需要更新持久化的消息的内容
            messageChatDto.setMsgId(message.getId());
            try {
                webSocketHandle.sendOneMessage(receiveId, JSONObject.toJSONString(messageChatDto));
                successCount++;
            } catch (Exception e) {
                message.setMsgStatus(WebSocketConstant.MSG_STATUS_ERROR)
                        .setFailCause(e.getMessage());
                baseMapper.updateById(message);
                failCount++;
                log.error("消息发送>>>>>>失败ID：" + message.getId());
            }
        }
        log.info("接收者总数：" + ids.size() + " >>>>成功发送数：" + successCount);
        log.info("接收者总数：" + ids.size() + " >>>>失败发送数：" + failCount);
        return true;
    }
}
